package com.jourwon.spring.boot.controller;

import com.jourwon.spring.boot.model.dto.UploadFile;
import com.jourwon.spring.boot.model.vo.CommonResponse;
import com.jourwon.spring.boot.service.FileStorageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 文件上传控制器
 *
 * @author JourWon
 * @date 2021/12/28
 */
@Slf4j
@RestController
@RequestMapping("/file")
@Api(value = "文件控制器")
public class FileUploadController {

    @javax.annotation.Resource
    FileStorageService fileStorageService;

    @PostMapping("/upload")
    @ApiOperation("上传文件")
    public CommonResponse upload(@RequestParam("file") MultipartFile file) {
        try {
            fileStorageService.save(file);
            return CommonResponse.success();
        } catch (Exception e) {
            return CommonResponse.failure();
        }
    }

    @GetMapping("/list")
    @ApiOperation("获取文件列表")
    public CommonResponse<List<UploadFile>> files(HttpServletResponse response) {
        List<UploadFile> files = fileStorageService.load()
                .map(path -> {
                    String fileName = path.getFileName().toString();
                    String url = MvcUriComponentsBuilder
                            .fromMethodName(FileUploadController.class, "getFile",
                                    path.getFileName().toString(), response).build().toString();
                    return new UploadFile(fileName, url);
                }).collect(Collectors.toList());

        return CommonResponse.success(files);
    }

    @GetMapping("/{filename:.+}")
    @ApiOperation("下载文件")
    public ResponseEntity<Resource> getFile(@PathVariable("filename") String filename, HttpServletResponse response) throws UnsupportedEncodingException {
        Resource file = fileStorageService.load(filename);
        String fileName = file.getFilename();
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        // 这里URLEncoder.encode可以防止中文乱码
        String fn = URLEncoder.encode(Objects.requireNonNull(fileName), StandardCharsets.UTF_8.name());

        // String utf8 = StandardCharsets.UTF_8.name();
        // // 方法1： 设置下载的文件的名称-该方式已解决中文乱码问题，swagger,postman看到的是%...等，浏览器直接输url,OK
        // response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
        //         "attachment;filename=" + URLEncoder.encode(fileName, utf8));
        // // 方法2： 设置下载的文件的名称-该方式已解决中文乱码问题，swagger,postman看到的是%...等，浏览器直接输url,OK（
        // // 把文件名按UTF-8取出并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码，中文不要太多，最多支持17个中文，因为header有150个字节限制。）
        // response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
        //         "attachment;filename=" + new String(fileName.getBytes(utf8), "ISO8859-1"));
        // // 方法3：设置下载的文件的名称-该方式已解决中文乱码问题，postman可以，swagger看到的是%...等，浏览器直接输url,OK
        // response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName + ";filename*=utf-8''"
        //         + URLEncoder.encode(fileName, utf8));

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "attachment;filename=" + fn)
                .body(file);
    }

}
